﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Ross.OA.Utility
{
    public class ReflectionHelper
    {
        public static List<Assembly> _Assemblies;
        public ReflectionHelper() {
            _Assemblies = AppDomain.CurrentDomain.GetAssemblies().ToList();
        }

        #region 类型搜索
        /// <summary>
        /// 获取子类型
        /// </summary>
        /// <param name="type">父类型</param>
        /// <returns></returns>
        public static IEnumerable<Type> GetSubTypes(Type type)
        {
            var assemblies = _Assemblies.Where(a =>
            {
                Assembly assembly = type.GetTypeInfo().Assembly;
                //基类所在程序集或依赖于基类的其他程序集
                return a.FullName == assembly.FullName || a.GetReferencedAssemblies().Any(ra => ra.FullName == assembly.FullName);
            });

            TypeInfo typeInfo = type.GetTypeInfo();

            return assemblies.SelectMany(a =>
            {
                return a.GetTypes().Where(t =>
                {
                    if (type == t)
                    {
                        return false;
                    }

                    TypeInfo tInfo = t.GetTypeInfo();

                    if (tInfo.IsAbstract || !tInfo.IsClass || !tInfo.IsPublic)
                    {
                        return false;
                    }

                    if (typeInfo.IsGenericTypeDefinition)
                    {
                        return type.IsConstructedGenericType;
                    }

                    return type.IsAssignableFrom(t);
                });
            });
        }

        /// <summary>
        /// 获取子类型
        /// </summary>
        /// <typeparam name="T">父类型</typeparam>
        /// <returns></returns>
        public static IEnumerable<Type> GetSubTypes<T>()
        {
            return GetSubTypes(typeof(T));
        }
        #endregion
    }
}
